//@author A0080440U
//
// **********
//
// **********

#include "Parser.h"

Parser::Parser(void){

}

Parser::~Parser(void){

}

// This function returns true if the string is a deadline
bool Parser::checkIfDeadline(const string & data) {

	string word = data.substr(0,3);
	string deadline = data.substr(3);
	int found = -1;

	if(word == ADD_BY) {
		found = deadline.find(MONDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(MON);
		if (found !=string :: npos) return true;
		found = deadline.find(TUESDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(TUE);
		if (found !=string :: npos) return true;
		found = deadline.find(WEDNESDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(WED);
		if (found !=string :: npos) return true;
		found = deadline.find(THURSDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(THU);
		if (found !=string :: npos) return true;
		found = deadline.find(FRIDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(FRI);
		if (found !=string :: npos) return true;
		found = deadline.find(SATURDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(SAT);
		if (found !=string :: npos) return true;
		found = deadline.find(SUNDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(SUN);
		if (found !=string :: npos) return true;
		found = deadline.find(TOMORROW);
		if (found == 0) return true;
		found = deadline.find(TMR);
		if (found == 0) return true;
		found = deadline.find(DAY_AFTER_TOMORROW);
		if (found == 0) return true;
		found = deadline.find(DAY_AFTER_TMR);
		if (found == 0) return true;
		found = deadline.find(SLASH);
		if (found == 1 || found == 2) return true;
		found = deadline.find(NEXT_WEEK);
		if (found == 0) return true;
		found = deadline.find(TODAY);
		if (found ==0) return true;
	}

	if(word == ADD_ON) {
		found = deadline.find(MONDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(MON);
		if (found !=string :: npos) return true;
		found = deadline.find(TUESDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(TUE);
		if (found !=string :: npos) return true;
		found = deadline.find(WEDNESDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(WED);
		if (found !=string :: npos) return true;
		found = deadline.find(THURSDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(THU);
		if (found !=string :: npos) return true;
		found = deadline.find(FRIDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(FRI);
		if (found !=string :: npos) return true;
		found = deadline.find(SATURDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(SAT);
		if (found !=string :: npos) return true;
		found = deadline.find(SUNDAY);
		if (found !=string :: npos) return true;
		found = deadline.find(SUN);
		if (found !=string :: npos) return true;
		found = deadline.find(SLASH);
		if (found == 1 || found == 2) return true;
	}

	if(word == ADD_IN) {
		if(deadline.find(FIND_DAY) != string :: npos)  return true;
	}


	return false;
}

//This function checks if the input is a day in a the week
bool Parser::checkIfDay(const string & deadline) {
	if(deadline == MONDAY || deadline == MON || deadline == TUESDAY || deadline == TUE || deadline == WEDNESDAY || 
		deadline == WED ||(deadline == THURSDAY || deadline== THU || deadline == FRIDAY || deadline == FRI || 
		deadline == SATURDAY || deadline== SAT) || deadline == SUNDAY || deadline== SUN) {
		return true;
	}
	return false;
}

// Thsi function ensure the date is valid
bool Parser:: checkIfValidDate(const string & deadline){
	string temp= deadline;
	size_t foundSlash= temp.find(SLASH);
	int day, month, year;
	

	istringstream InStreamDay(temp.substr(0,temp.size()-foundSlash));
	InStreamDay>> day;
	foundSlash++;
	temp = temp.substr(foundSlash,temp.size()-foundSlash);
	foundSlash= temp.find(SLASH);
	
	istringstream InStreamMonth(temp.substr(0,temp.size()-foundSlash));
	InStreamMonth>> month;
	foundSlash++;
	temp = temp.substr(foundSlash,(temp.size()-foundSlash));
	
	istringstream InStreamYear(temp);
	InStreamYear>> year;

	int maxDays;

	if (month >0 && month <=12) {
		maxDays=DAYS[month-1];
		if(year%4 ==0 && month ==2) {
			maxDays= 29;
		}
		if (day>0 && day <=maxDays){
			return true;
		}
	} 

	return false;
}

// This function checks if date is a date
bool Parser::checkIfDate(const string & deadline) {
	size_t foundSlash= deadline.find(SLASH);
	if(foundSlash!= string :: npos){
		if(deadline[1] == SLASH || deadline[2] == SLASH) {
			if(!checkIfValidDate(deadline)){
				throw exception ("Invalid date");
			}
			return true;
		}
		throw exception ("Invalid date");
	}
	return false;
}

// This function takes in the flexible commands and converts it to days to be added to the present day
int Parser::convertToDays(const string & deadline){
	
	if(deadline == MONDAY || deadline == MON) {
		return 1;
	} else if(deadline == TUESDAY || deadline == TUE) {
		return 2;
	} else if(deadline == WEDNESDAY ||deadline == WED) {
		return 3;
	} else if(deadline == THURSDAY || deadline == THU) {
		return 4;
	} else if(deadline == FRIDAY || deadline== FRI) {
		return 5;
	} else if(deadline == SATURDAY || deadline== SAT) {
		return 6;
	} else if(deadline == SUNDAY || deadline == SUN) {
		return 7;
	} else if (deadline == TODAY) {
		return 0;	
	} else {
		return -1;
	}
}

// This function taskes in an instruction and converts the deadlien into a date with standard format. 
// it accepts flexible commands
string Parser::convertToDate(const string & instruction, string & deadline) {
	
	if(checkIfDate(deadline)) {
		return deadline;
	}

	string date;
	int daysToBeAdded = -1;
	int monthsToBeAdded = 0;
	bool This= false;
	bool next= false;

	if (instruction == LATER) {
		daysToBeAdded =0;
	}

	if(instruction == ADD_IN) {
		if(deadline.find(FIND_DAY)!= string ::npos) {
			daysToBeAdded= atoi(deadline.substr(0,deadline.find(FIND_DAY)).c_str());
			if (daysToBeAdded<=0) {
				throw exception ("Invalid day");
			}
		} 
	} else if(instruction == ADD_BY || instruction == ADD_ON){
		size_t foundThis= deadline.find(FIND_THIS);
		size_t foundNext= deadline.find(FIND_NEXT);

		if( foundThis != string:: npos ) This= true;
		if( foundNext != string:: npos ) next= true;

		if(This || next) {
			deadline = deadline.substr(5);
		}

		if(deadline == DAY_AFTER_TMR || deadline == DAY_AFTER_TOMORROW) {
			daysToBeAdded = 2;
		} else if (deadline == TMR || deadline == TOMORROW){
			daysToBeAdded = 1;
		} else if(deadline == NEXT_WEEK){
			daysToBeAdded = 7;
		}else {
			daysToBeAdded = convertToDays(deadline);
		}
	}

	if(daysToBeAdded < 0) {
		throw exception  ("deadline error");		
	}
	
	time_t rawtime;
	time(&rawtime);
	struct tm *currentTime = localtime(&rawtime);
	currentTime->tm_hour = 0; currentTime->tm_min = 0; currentTime->tm_sec = 0;
	time_t today = mktime(currentTime);
	
	if (daysToBeAdded ==0) {
		ostringstream OutStream;
		OutStream << currentTime->tm_mday<< DATE_SLASH<< currentTime->tm_mon+1 << DATE_SLASH << (currentTime->tm_year+1900)%100;
		return OutStream.str();
	}

	if(checkIfDay(deadline)) {
		if(currentTime->tm_wday >= daysToBeAdded) { // lets say today is wed, you say by mon. means next mon. AUTO NEXT
			if (This) throw exception ("Did you mean 'next' ?");
			daysToBeAdded = 7 - (currentTime->tm_wday - daysToBeAdded);
		} else {
			daysToBeAdded= daysToBeAdded-currentTime->tm_wday;
			if(next) {
				daysToBeAdded+=7;
			}
		}
	}

	int secondsToBeAdded = 60*60*24*daysToBeAdded; 

//	return to_string(secondsToBeAdded);

	today += secondsToBeAdded;

	struct tm * deadlineTime = localtime(&today);

	date = to_string(deadlineTime->tm_mday) + DATE_SLASH + to_string(deadlineTime->tm_mon+1) + DATE_SLASH + to_string((deadlineTime->tm_year+1900)%100);		// +1 cause convention is jan = 0,
	
	return date;
}


// This function converts task into string
string Parser::convertToString(Task task) {
	ostringstream os;
	
	if(task.getTaskName() != EMPTY) {
		os << task.getTaskName();
	}
	if(task.getDeadline() != EMPTY) {
		os << CONVERT_BY << task.getDeadline();
	}
	if(task.getTime() != EMPTY) {
		os << CONVERT_AT << task.getTime();
	}
	if(task.getPriority() != EMPTY) {
		os << CONVERT_PRIORITY << task.getPriority();
	}
	if(task.getStatus() == CMI) {
		os << CONVERT_CMI;
	}
	if(task.getStatus() == DONE) {
		os << CONVERT_DONE;
	}
	if(task.getStatus() == ARCHIVE) {
		os << CONVERT_ARCHIVE;
	}
	if(task.getDateInSeconds() != NIL) { 
		os << CONVERT_AND << task.getDateInSeconds();
	}
	return os.str();
}

// This function is used to find out if auto PM is needed
bool Parser::pmFound(vector<string> &PMDirectory, string &task){
	istringstream inStream(task);
	string keyword;
	while (inStream >> keyword){
		vector<string> :: iterator iter= PMDirectory.begin();
		while(iter!= PMDirectory.end()){
			if(*iter== keyword){
				return true;
			}
			++iter;
		}
	}
	return false;
}

//This function is used for smart time
bool Parser::lunchFound(string &task) {
	size_t foundLunch= task.find(LUNCH);
	if (foundLunch!=string::npos) {
		return true;
	}
	return false;
}

// This function checks if the time is valid
void Parser:: checkForValidTime(double time) {
	if(int (time) <0) {
		throw exception("Invalid time");
	}
	if (int(time)%100 > 59){ //invalid time (minutes)
		throw exception("Invalid time");
	}

	if (int(time/100) > 23) {
		throw exception("Invalid time");
	}
}

// this function converts one time into the standard 24hr format
string Parser::convertToTimeFormat(string &deadline, bool &PM, bool &lunch){
	double time;
	bool specifiedPM= false;
	bool specifiedAM= false;
	int index=0;

	if(deadline.find(COLON) != string:: npos) {
		deadline[deadline.find(COLON)]= DOT;
	}

	size_t found=deadline.find(SPECIFIED_AM);  // whole chunk checks if am or pm is specified.
	if (found!=string::npos) {
		specifiedAM= true;
	} else {
		found=deadline.find(SPECIFIED_PM);
		if (found!=string::npos) {
		specifiedPM= true;
		}
	} 


	// if not specified, check if time is specified n 24 hrs or not
	// return into a string
	if (specifiedPM) { // pm is specified by user
		deadline = deadline.substr(0, found);
		while(index<deadline.size()){
			if((deadline[index]<CHAR_ZERO || deadline[index]>CHAR_NINE) && deadline[index] != DOT && deadline[index]!= WHITE_SPACE){
				throw exception ("Invalid time");
			}
			index++;
		}
		istringstream IN(deadline);
		IN>> time;
		checkForValidTime(time);
		if (time < 13.00) { // not 24hrs
			time *=100;
		}
		if(time <1200){
			time += 1200;
		}
	} else if (specifiedAM) { // am is specified by user
		deadline= deadline.substr(0, found);
		while(index<deadline.size()){
			if((deadline[index]<CHAR_ZERO || deadline[index]>CHAR_NINE) && deadline[index] != DOT && deadline[index]!= WHITE_SPACE){
				throw exception ("Invalid time");
				}
			index++;
			}
		istringstream IN(deadline);
		IN>> time;
		checkForValidTime(time);
		if (time < 13.00) { // not 24hrs
			time *=100;
		} 
		if (time>=1200 && time <1300){
			time-=1200;
		}

	} else { // unspecified am or pm
		while(index<deadline.size()){
			if((deadline[index]<CHAR_ZERO || deadline[index]>CHAR_NINE) && deadline[index] != DOT && deadline[index]!= WHITE_SPACE){
				throw exception ("Invalid time");
				}
			index++;
			}
		istringstream IN(deadline);
		bool change= true;
		if (deadline[0]==CHAR_ZERO && deadline[1]==CHAR_ZERO) {
			change = false;
		}
		IN>> time;
		checkForValidTime(time);
		if (time < 24.00 && change) { // not 24hrs
			time *=100;
		} else if (deadline.size()==4) {
			change = false;
		}

		if (PM && change) { // if the detector detects it to be pm
			if(time <=1200){ //check if already in 24hr format
				time +=1200;
			}
		} else if (lunch && change) {
			if(time < 700) {
				time +=1200;
			}
		} else if (time <900 && change) {
			time += 1200;
		}
	}
	
		ostringstream convert;
		string outputTime;
		convert << time;
		outputTime= convert.str();

		if(outputTime.size() <3) {
			outputTime= ZEROS+outputTime;
		}
		if( outputTime.size() != 4) {
			outputTime = ZERO + outputTime;
		}

		if(outputTime.size() != 4) {
			throw exception ("Invalid time");
		}
		return outputTime;
}

// This function checks if the timing specified has one or two timings
bool Parser::checkIfSingle(string &deadline){
	size_t foundDash=deadline.find(CHECK_DASH);  
	size_t foundTo=deadline.find(CHECK_TO);  
	if (foundDash==string::npos && foundTo==string::npos) {
		return true; // it is single time
	}
	return false;
}

// this functiom takes in a string and converts it into a time format. 
// It will determine if there are 2 timing specified and arrange accordingly
string Parser::executeTimeConversion(string &deadline, bool &PM, bool &lunch){
	ostringstream outStream;
	string start, end;

	if(deadline== DASH) {
		return SPACE;
	}

	// if only one timign is specified, convert one
	if(checkIfSingle(deadline)){
		return convertToTimeFormat(deadline, PM, lunch);
	} else {
		size_t foundDash=deadline.find(CHECK_DASH);  
		size_t foundTo=deadline.find(CHECK_TO);  
		if (foundDash!=string::npos){
			start= deadline.substr(0, foundDash);
			foundDash++;
			end= deadline.substr(foundDash, (deadline.size()-foundDash));
		} else if (foundTo!=string::npos){
			start= deadline.substr(0, foundTo);
			foundTo+= 2;
			end= deadline.substr(foundTo, (deadline.size()-foundTo));
			}
		while (end[0]== WHITE_SPACE){
			end= end.substr(1, end.size()-1);
		}
		while (start[0]== WHITE_SPACE){
			start= start.substr(1, end.size()-1);	
		} 
		outStream << convertToTimeFormat(start, PM, lunch) << CHECK_DASH << convertToTimeFormat(end, PM, lunch);
	}	
	
	return outStream.str();
}

// this function removes whitespeaces from the two ends of the string
void Parser::removeWhiteSpaces(string  & line) {
	if(line.size () == NIL) {
		return;
	}

	while(line[0] == WHITE_SPACE) {
		if(line.size() == 1) {
			line = EMPTY;
			return;
		} else {
			line = line.substr(1);
		}
	}
		
	while(line[line.size()-1] == WHITE_SPACE) {
		if(line.size() == 1) {
			line = EMPTY;
			return;
		} else {
			line = line.substr(0,line.size()-1);
		}
	}
	return;
}

// this function removes the year indicated from the date
void Parser::trimAwayYearFromDate(string & deadline) {
	int firstSlash = deadline.find_first_of(SLASH);
	int secondSlash = deadline.find_first_of(SLASH,firstSlash+1);

	if(secondSlash != string::npos) {
		deadline = deadline.substr(0,secondSlash);
	}
	return;
}

// this function determines what the input wants to do, and parses it
Task Parser::convertUserInputToTask(string input, string & command) {
	
	if(input.find_first_of(STAR_AND) != string::npos) {
		throw exception ("Symbols * and & are not allowed as inputs, while ! and @ are reserved for priority and time inputs");
	}

	// the 9 variables avaiable in class Task
	string taskName = EMPTY;
	string deadline = EMPTY;
	string priority = LOW;
	string modifiedTaskName = EMPTY;
	string modifiedDeadline = EMPTY;
	string modifiedPriority = EMPTY;
	string modifiedTime = EMPTY;
	string modifiedStatus = EMPTY;		// this is for marking if complete or CMI
	string time = EMPTY; 
	int taskLine = NIL;
	
	bool PM= false;
	bool lunch= false;

	string keyword = EMPTY;
	string syntax = EMPTY;
	string temporary = EMPTY;
	Task task;

	istringstream inStream(input);

	inStream >> command;
	
	if (command == ADD) {
					
		string data;
		getline(inStream, data);
		removeWhiteSpaces(data);

		if(!data.empty()) {
						
			// start finds where priority starts from
			// extract priority out, remove it from the data string
			int start = data.find(SYMBOL_PRIORITY);
			if(start != string::npos) {
				priority = data.substr(start+1);
				data = data.substr(0,start);
			}
			removeWhiteSpaces(data);


			// find where time starts from
			// extract the time out, remove it from data stirng
			start = data.find(SYMBOL_TIME);
			if(start != string::npos) {
				time = data.substr(start+1);
				data = data.substr(0,start);
			}
			removeWhiteSpaces(data);


			// finding the last on/in/by 
			// in case the userinput has more than one of those
			// e.g. watch the day after tmr by the day after tmr
			int winner = NIL;
			int startBY = data.find(ADD_BY);
			int startIN = data.find(ADD_IN);
			int startON = data.find(ADD_ON);
			
			while (startBY != string::npos || startIN != string::npos || startON != string::npos) {
				winner = max(winner,startBY);
				winner = max(winner,startON);
				winner = max(winner,startIN);
				if(startBY != string::npos) {
					startBY = data.find(ADD_BY,startBY+1);
				}
				if(startIN != string::npos) {
					startIN = data.find(ADD_IN,startIN+1);
				}
				if(startON != string::npos) {
					startON = data.find(ADD_ON,startON+1);
				}
			}
			//if one of those on/by/in is found, first, check if it is a deadline
			if(winner != NIL) {
				if(checkIfDeadline(data.substr(winner))) {
					deadline = data.substr(winner);
					
					// next 3 lines is to accept tues, thurs by making it tue and thu
					int found = deadline.find(SLASH);
					int foundDays= deadline.find(FIND_DAY);
					if(found == string::npos && foundDays == string::npos && deadline.substr(3)!= DAY_AFTER_TMR && deadline.substr(3)!= DAY_AFTER_TOMORROW && deadline.substr(3)!= TOMORROW && deadline.substr(3)!= TODAY){
						size_t foundThis= deadline.find(FIND_THIS);
						size_t foundNext= deadline.find(FIND_NEXT);
						if (foundThis == string:: npos && foundNext== string ::npos) {
							deadline = deadline.substr(0,6);
						} else {
							deadline = deadline.substr(0,11);
						}
					}
					data = data.substr(0,winner);											
				}
			}
					
			taskName = data.substr(0);			
			
		}	
	
	} else if (command == DISPLAY) {
		inStream >> taskName;
		if(taskName == EMPTY) {
			taskName = DEFAULT; // default display by deadline-> priority
		}


	} else if (command == MODIFY) {					
		// for now we only can modify by lineNumber, to be upgraded later on 
		// to be able to modify by taskname

		inStream >> taskLine;
		getline(inStream,modifiedTaskName); // @ or ! or taskname goes into taskName to be extracted later

		// getting rid of whitespace if have
		removeWhiteSpaces(modifiedTaskName);
		if(taskLine != NIL && modifiedTaskName != EMPTY) {

			if(modifiedTaskName.size() > 3) {
				if(checkIfDeadline(modifiedTaskName)) {
					modifiedDeadline = modifiedTaskName;
					modifiedTaskName = EMPTY;
				}
			} 
			
			if(modifiedTaskName[0] == SYMBOL_PRIORITY) {
				int start = modifiedTaskName.find_first_not_of(WHITE_SPACE,1);
				if(start != string::npos) {
					modifiedPriority = modifiedTaskName.substr(start); // removes symbol from priority
		//		} else {
		//			modifiedPriority = modifiedTaskName.substr(1);
				}
				modifiedTaskName = EMPTY;
			
			} else if(modifiedTaskName[0] == SYMBOL_TIME) {
				
				int start = modifiedTaskName.find_first_not_of(WHITE_SPACE,1);
		
				
				if(start != string::npos) {
					modifiedTime = modifiedTaskName.substr(start); // removes symbol from time
				}
					
				modifiedTaskName = EMPTY;
			}
		}

	
	} else if (command == DELETE_) {
	
		inStream >> taskName;
		istringstream inStream2(taskName);
		int i = 0;
		inStream2 >> i;
		taskName = EMPTY;
		taskLine = i;


	} else if (command == SEARCH) {
		getline(inStream,taskName);
		removeWhiteSpaces(taskName);
		
	} else if (command == MARK) {
		inStream >> taskLine;
		inStream >> modifiedStatus;
	
	} else if (command == FILTER) {
		inStream >> taskName;
	} else if (command == SORT) {
		inStream >> taskName;
	}


	removeWhiteSpaces(taskName);
	removeWhiteSpaces(deadline);
	removeWhiteSpaces(priority);
	removeWhiteSpaces(modifiedPriority);

	//splitting up to get the command and the deadline itself
	if(deadline != EMPTY) {
		string command1 = deadline.substr(0,3);
		string partialDeadline = deadline.substr(3);
		deadline = convertToDate(command1,partialDeadline);
	}
	
	if(modifiedDeadline != EMPTY) {
		string command1 = modifiedDeadline.substr(0,3);
		string partialDeadline = modifiedDeadline.substr(3);
		modifiedDeadline = convertToDate(command1,partialDeadline);
	}
	
	if(modifiedTime != EMPTY) {
		modifiedTime = executeTimeConversion(modifiedTime, PM, lunch);
	}

	if(priority == HIGH_FAST) {
		priority = HIGH;
	}
	if(priority == MEDIUM_FAST) {
		priority = MEDIUM;
	}
	if(priority == LOW_FAST) {
		priority = LOW;
	}
	if(priority == HIGH || priority == MEDIUM || priority == LOW || priority == EMPTY) {
	} else {
		throw exception("Invalid priority. Available priorities: high/medium/low");
	}
	if(modifiedPriority == HIGH_FAST) {
		modifiedPriority = HIGH;
	}
	if(modifiedPriority == MEDIUM_FAST) {
		modifiedPriority = MEDIUM;
	}
	if(modifiedPriority == LOW_FAST) {
		modifiedPriority = LOW;
	}
	
	if(modifiedPriority == HIGH || modifiedPriority == MEDIUM || modifiedPriority == LOW || modifiedPriority == EMPTY) {
	} else {
		throw exception("Invalid priority to be modified to. Available priorities: high/medium/low");
	}

	if(time != EMPTY) {
		removeWhiteSpaces(time);
		time = executeTimeConversion(time, PM, lunch);
	
	}
	
	if(time != EMPTY){
		vector<string> PMDirectory;
		PMDirectory.push_back(DINNER);
		PMDirectory.push_back(SUPPER);

		// checks if there is a need to use the auto time
		PM= pmFound(PMDirectory, taskName);
		lunch = lunchFound(taskName);
		while (time[0]== WHITE_SPACE) {
			time= time.substr(1, deadline.size()-1);
		}
		time= executeTimeConversion(time, PM, lunch);
	}

//	 ensure timing is within 0000-2359
	if(time!= EMPTY) {
		if(atoi(time.substr(0,2).c_str()) > 23 || atoi(time.substr(0,2).c_str()) < 0)
			throw exception("Invalid time");
		if(atoi(time.substr(2,2).c_str()) > 59 || atoi(time.substr(2,2).c_str()) < 0) 
			throw exception("Invalid time");
	}

	if(modifiedTime != EMPTY && modifiedTime != " ") {
		if(atoi(modifiedTime.substr(0,2).c_str()) > 23 || atoi(modifiedTime.substr(0,2).c_str()) < 0)
			throw exception("Invalid time");
		if(atoi(modifiedTime.substr(2,2).c_str()) > 59 || atoi(modifiedTime.substr(2,2).c_str()) < 0) 
			throw exception("Invalid time");
	}

	
	task.changeTaskName(taskName);
	task.changeDeadline(deadline);
	if(deadline != EMPTY) {
		task.changeDateInSeconds();
	} 
	if(task.getDateInSeconds() < 0) {
		throw exception("deadline error");
	}
	trimAwayYearFromDate(deadline);		// sometimes will have the year behind, sometimes wont. im deleting it away cause the year is stored in dateInSeconds, not deadline
	task.changeDeadline(deadline);
	task.changePriority(priority);
	if(time == EMPTY) {
		time = WHITE_SPACE;
	}
	task.changeTime(time);
	
	task.changeTaskLine(taskLine);
	task.changeModifiedDeadline(modifiedDeadline);
	if(modifiedDeadline != EMPTY) {
		task.changeModifiedDateInSeconds();
	}
	if(task.getModifiedDateInSeconds() < 0) {
		throw exception ("deadline error");
	}

	trimAwayYearFromDate(modifiedDeadline);
	task.changeModifiedDeadline(modifiedDeadline);
	task.changeModifiedPriority(modifiedPriority);
	task.changeModifiedTaskName(modifiedTaskName);
	task.changeModifiedTime(modifiedTime);
	task.changeModifiedStatus(modifiedStatus);

	return task;
}

Task Parser::convertToTask(string input) {
	
	// the 9 variables avaiable in class Task
	string command = EMPTY;
	string taskName = EMPTY;
	string deadline = EMPTY;
	string priority = EMPTY;
	string status = WIP;
	string modifiedTaskName = EMPTY;
	string modifiedDeadline = EMPTY;
	string modifiedPriority = EMPTY;
	string time = EMPTY; 
	time_t dateInSeconds = NIL;
	int taskLine = NIL;
	

	string keyword = EMPTY;
	string syntax = EMPTY;
	string temporary = EMPTY;
	
	istringstream inStream(input);
	string data = input; // to make things simple as i copied from the function above
	
	int start = data.find(SYMBOL_DATE_IN_SECONDS);
	if(start > 0) {
		int temp = atoi(data.substr(start+2).c_str());
		dateInSeconds = temp;
		data = data.substr(0,start);
	}

	start = data.find(SYMBOL_STATUS);
	if(start > 0) {
		status = data.substr(start+2);
		data = data.substr(0,start);
	}

	while(data.back() == WHITE_SPACE) {
		data = data.substr(0,data.size()-1);
	}

	// start finds where priority starts from
	// extract priority out, remove it from the data string
	start = data.find(SYMBOL_PRIORITY);
	if(start > 0) {
		priority = data.substr(start+1);
		data = data.substr(0,start);
	}

	while(data.back() == WHITE_SPACE) {
		data = data.substr(0,data.size()-1);
	}

	// find where time starts from
	// extract the time out, remove it from data stirng
	start = data.find(SYMBOL_TIME);
	if(start > 0) {
		time = data.substr(start+1);
		data = data.substr(0,start);
	}

	while(data.back() == WHITE_SPACE) {
		data = data.substr(0,data.size()-1);
	}

	int winner = NIL;
	int startBY = data.find(ADD_BY);
	int startIN = data.find(ADD_IN);
	int startON = data.find(ADD_ON);
			
	while (startBY != string::npos || startIN != string::npos || startON != string::npos) {
		winner = max(winner,startBY);
		winner = max(winner,startON);
		winner = max(winner,startIN);
		if(startBY != string::npos) {
			startBY = data.find(ADD_BY,startBY+1);
		}
		if(startIN != string::npos) {
			startIN = data.find(ADD_IN,startIN+1);
		}
		if(startON != string::npos) {
				startON = data.find(ADD_ON,startON+1);
			}
	}
			
	if(winner != NIL) {
		if(checkIfDeadline(data.substr(winner))) {
			deadline = data.substr(winner);
			data = data.substr(0,winner);											
		}
	}
	
	taskName = data.substr(0);			
			
		
			
			
	// following 6 while loops are to remove whitespaces
	// in either the taskName or deadline or priority
	removeWhiteSpaces(taskName);
	removeWhiteSpaces(deadline);
	removeWhiteSpaces(priority);
	removeWhiteSpaces(status);
	removeWhiteSpaces(time);

	Task task;
	
	if(deadline != EMPTY) {
		string command1 = deadline.substr(0,3);
		string partialDeadline = deadline.substr(3);
		deadline = convertToDate(command1,partialDeadline);
	}
	
	
	task.changeTaskName(taskName);
	task.changeDeadline(deadline);
	task.changeDateInSeconds(dateInSeconds);
	task.changePriority(priority);
	if(time == EMPTY) {
		time = WHITE_SPACE;
	}
	task.changeTime(time);
	task.changeStatus(status);
	return task;
}
